#include "lua_bitop.h"
#include "lua_utils.h"
#include <string>
#include "Win32Utils/CPathUtils.h"
#include "Win32Utils/CStrUtils.h"

static luaL_Reg lib_functions[] =
{
    { "And", &lua_bitop::And},
    { "Or", &lua_bitop::Or},
    { "Xor", &lua_bitop::Xor},
    { "Bit", &lua_bitop::Bit},
    { NULL, NULL}
};

void lua_bitop::initialize(lua_State* L, const char* lib_name)
{
    lua_newtable(L);

    luaL_Reg* fun_info = lib_functions;
    while (fun_info->func)
    {
        lua_pushcfunction(L, fun_info->func);
        lua_setfield(L, -2, fun_info->name);
        fun_info++;
    }
    lua_setfield(L, -2, lib_name);
}

void lua_bitop::uninitialize()
{

}

int lua_bitop::And(lua_State* L)
{
    int top = lua_gettop(L);
    int result = 0;

    if (top >= 1 && lua_isnumber(L, 1))
    {
        result = lua_tointeger(L, 1);
    }

    for (int i = 2; i <= top; i++)
    {
        if (lua_isnumber(L, i))
        {
            result = result & lua_tointeger(L, i);
        }
    }

    lua_pushinteger(L, result);

    return 1;
}

int lua_bitop::Or(lua_State* L)
{
    int top = lua_gettop(L);
    int result = 0;

    if (top >= 1 && lua_isnumber(L, 1))
    {
        result = lua_tointeger(L, 1);
    }

    for (int i = 2; i <= top; i++)
    {
        if (lua_isnumber(L, i))
        {
            result = result | lua_tointeger(L, i);
        }
    }

    lua_pushinteger(L, result);

    return 1;
}

int lua_bitop::Xor(lua_State* L)
{
    int top = lua_gettop(L);
    int result = 0;

    if (top >= 1 && lua_isnumber(L, 1))
    {
        result = lua_tointeger(L, 1);
    }

    for (int i = 2; i <= top; i++)
    {
        if (lua_isnumber(L, i))
        {
            result = result ^ lua_tointeger(L, i);
        }
    }

    lua_pushinteger(L, result);

    return 1;
}

int lua_bitop::Bit(lua_State* L)
{
    int top = lua_gettop(L);
    int result = 0;

    for (int i = 1; i <= top; i++)
    {
        if (lua_isnumber(L, i))
        {
            result |= 1 << lua_tointeger(L, i);
        }
    }

    lua_pushinteger(L, result);

    return 1;
}
